﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Net;
using System.Net.Cache;
using System.Text;
using System.Web;
using System.Linq;
using Klinkby.Properties;

namespace Klinkby
{
    static class RemoteContent
    {
        readonly static Uri sourceUrl = new Uri(
            ConfigurationManager.AppSettings["sourceUrl"],
            UriKind.Absolute);
        readonly static string targetUrl = ConfigurationManager.AppSettings["targetUrl"];

        public static IAsyncResult Fetch(
            Uri uri,
            string httpMethod,
            Func<byte[]> getRequestBody,
            Action<HttpWebResponse, IAsyncResult, WebException> callback)
        {
            var request = CreateBrowserlikeRequest(uri, httpMethod, getRequestBody);
            var result = request.BeginGetResponse(
                asyncResult =>
                {
                    try
                    {
                        using (var res = (HttpWebResponse)request.EndGetResponse(asyncResult))
                            callback(res, asyncResult, null);
                    }
                    catch (WebException e)
                    {
                        callback(null, asyncResult, e);
                    }
                }, null);
            return result;
        }

        public static Uri GetUrl(HttpRequest request)
        {
            return new Uri(
                sourceUrl,
                request.AppRelativeCurrentExecutionFilePath
                    .Replace("~", string.Empty)
                    .ReplaceLastIgnoreCase(Resources.DefaultAspx, string.Empty)
                    + (!string.IsNullOrEmpty(request.Url.Query) ? "?" + request.Url.Query : string.Empty)
                    );
        }

        private static HttpWebRequest CreateBrowserlikeRequest(
            Uri uri,
            string httpMethod,
            Func<byte[]> getRequestBody)
        {
            var req = (HttpWebRequest)HttpWebRequest.Create(uri);
            req.AutomaticDecompression = DecompressionMethods.Deflate;
            req.KeepAlive = true;
            req.AllowAutoRedirect = true;            
            req.Accept = Resources.HttpAccept;
            req.Headers.Add(HttpRequestHeader.AcceptCharset, Resources.HttpAcceptCharset);
            req.Headers.Add(HttpRequestHeader.AcceptEncoding, Resources.HttpAcceptEncoding);
            req.Referer = uri.AbsoluteUri;
            req.UserAgent = Resources.UserAgent;
            req.Method = httpMethod;
            if (string.Compare(httpMethod, Resources.HttpPost, StringComparison.OrdinalIgnoreCase) == 0)
            {
                // rewrite the original post body
                var buf = getRequestBody();
                req.ContentLength = buf.Length;
                req.ContentType = Resources.HttpPostContentType;
                using (var reqStream = req.GetRequestStream())
                {
                    reqStream.Write(buf, 0, buf.Length);
                }
                req.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
            }
            else
            {
                req.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Default);
            }
            return req;
        }
    }
}